namespace dw {
	namespace system {
		/// Serialization

inline Serializer::Serializer(std::iostream* stream)
:	_os(stream)
,	_is(stream)
{
}

inline Serializer::Serializer(std::ostream* os, std::istream* is)
:	_os(os)
,	_is(is)
{
}

inline void Serializer::Serialize(const bool data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (bool));
}

inline void Serializer::Serialize(const char data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (char));
}

inline void Serializer::Serialize(const unsigned char data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (unsigned char));
}

inline void Serializer::Serialize(const short data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (short));
}

inline void Serializer::Serialize(const unsigned short data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (unsigned short));
}

inline void Serializer::Serialize(const int data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (int));
}

inline void Serializer::Serialize(const unsigned int data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (unsigned int));
}

inline void Serializer::Serialize(const float data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (float));
}

inline void Serializer::Serialize(const double data)
{
	_os->write(reinterpret_cast< const char* >(&data), sizeof (double));
}

template< typename InputIterator >
inline void Serializer::SerializeRange(const InputIterator& begin, const InputIterator& end, const size_t size)
{
	Serialize(static_cast< unsigned >(size));
	for (InputIterator it = begin; it != end; ++it)
		Serialize(*it);
}

template< typename InputIterator >
inline void Serializer::SerializeRange(const InputIterator& begin, const InputIterator& end)
{
	SerializeRange(begin, end, end - begin);
}

inline void Serializer::Serialize(const std::string& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

template< typename T1, typename T2 >
inline void Serializer::Serialize(const std::pair< T1, T2 >& obj)
{
	Serialize(obj.first);
	Serialize(obj.second);
}

template< typename T >
inline void Serializer::Serialize(const std::vector< T >& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

template< typename T >
inline void Serializer::Serialize(const std::list< T >& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

template< typename Key, typename Compare >
inline void Serializer::Serialize(const std::set<Key, Compare>& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

template< typename Key, typename Compare >
inline void Serializer::Serialize(const std::multiset<Key, Compare>& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

template< typename Key, typename Data, typename Compare >
inline void Serializer::Serialize(const std::map<Key, Data, Compare>& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

template< typename Key, typename Data, typename Compare >
inline void Serializer::Serialize(const std::multimap<Key, Data, Compare>& obj)
{
	SerializeRange(obj.begin(), obj.end(), obj.size());
}

inline void Serializer::Serialize(const ISerializable& obj)
{
	obj.serialize(this);
}

template< typename T >
inline void Serializer::Serialize(const T* objPtr)
{
	dwAssert(objPtr != NULL, "Invalid parameter: obj == NULL");

	serialize(*objPtr);
}



/// Deserialization



inline void Serializer::Deserialize(bool& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (bool));
}

inline void Serializer::Deserialize(char& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (char));
}

inline void Serializer::Deserialize(unsigned char& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (unsigned char));
}

inline void Serializer::Deserialize(short& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (short));
}

inline void Serializer::Deserialize(unsigned short& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (unsigned short));
}

inline void Serializer::Deserialize(int& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (int));
}

inline void Serializer::Deserialize(unsigned int& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (unsigned int));
}

inline void Serializer::Deserialize(float& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (float));
}

inline void Serializer::Deserialize(double& data)
{
	_is->read(reinterpret_cast< char* >(&data), sizeof (double));
}

inline void Serializer::Deserialize(std::string& obj)
{
	obj.clear();
	DeserializeRange(std::back_inserter(obj));
}

template< typename T >
inline void Serializer::Deserialize(std::vector< T >& obj)
{
	obj.clear();
	DeserializeRange(std::back_inserter(obj));
}

template< typename T >
inline void Serializer::Deserialize(std::list< T >& obj)
{
	obj.clear();
	DeserializeRange(std::back_inserter(obj));
}

template< typename Key, typename Compare >
inline void Serializer::Deserialize(std::set<Key, Compare>& obj)
{
	obj.clear();
	DeserializeRange(std::inserter(obj, obj.end()));
}

template< typename Key, typename Compare >
inline void Serializer::Deserialize(std::multiset<Key, Compare>& obj)
{
	obj.clear();
	DeserializeRange(std::inserter(obj, obj.end()));
}

template< typename Key, typename Data, typename Compare >
inline void Serializer::Deserialize(std::map<Key, Data, Compare>& obj)
{
	obj.clear();
	DeserializeRange(std::inserter(obj, obj.end()));
}

template< typename Key, typename Data, typename Compare >
inline void Serializer::Deserialize(std::multimap<Key, Data, Compare>& obj)
{
	obj.clear();
	DeserializeRange(std::inserter(obj, obj.end()));
}

inline void Serializer::Deserialize(ISerializable& obj)
{
	obj.deserialize(this);
}

template< typename T >
inline void Serializer::Deserialize(T* objPtr)
{
	objPtr = new T();
	Deserialize(*objPtr);
}

	} // namespace system
} // namespace dw
